User blog:Dfjdejulio/Logic Exercise: FizzBuzz
Logic Exercise: Fizz Buzz I've been looking for a simple logic programming project to use in a sort of tutorial or exercise level. There is a common very simple programming task that's used to weed out people who do not know how to program in job interviews. It's called "Fizz Buzz", and the rules are as follows: Write a program to count from 1 to 100, but whenever you reach a number divisible by three, say "fizz" instead of the number, and whenver you reach a number divisible by five, say "buzz" instead of the number. If the number is divisible by both three and five, say "fizz buzz". I figure if I can do that with logic in Infinity, I'm ready to start tackling real projects. The Final Circuit Layout Here's the final circuit layout. (And Iron Man is awesome for debugging, because he can easily fly over circuit boards.) They most important pieces were the "Time Delayer", the "Logic Gate", and the "Dual Action Trigger". Time Delayer The "Time Delayer" was important because the whole thing is a massively parallel message-passing system, and introducing delays on purpose was the only way to make the steps happen in the correct order. Logic Gate The "Logic Gate" receives three messages, two of which trigger state changes and the third of which triggers an output message. The state-changing messages are "open" and "close". When you send it the "input" message and it's in the "open" state, it sends its own "output" message to any targets of that signal. When you send it the "input" message and it's in the "closed" state, it sends its own "input blocked" message to targets of that signal. So it's a way to say "send a message unless you've been told not to", with an optional "when that happens, send this other message instead". Dual Action Trigger The "Dual Action Trigger" takes three messages: "Input 1", "Input 2", and "Reset". When it has recived both an "Input 1" and an "Input 2", it sends out a "Complete" message. When it gets a "Reset" message, it "forgets" any "Input 1" or "Input 2" messages it's gotten. A Debugging Tip If you've got a multi-step "program" to "run", the logical way to do that is to use a "Repeater". But in real programming, when you want to debug your program, a very common thing is to single-step through it, running one line at a time. So, I have a repeater, but all it does is send a signal to a button. That way I can run the program by turning on the repeater, or I can single-step through by pushing that button myself. The Important Sections (I still stink at wikia layout, apparently. I'll clean this up later.) Control Circuit This is the control circuit for the whole thing. There's a color-changing block, a repeater, and two buttons. One button turns the block green (so you can see that the program is running) and turns on the repeater. The other button turns the block red, turns off the repeater, and resets all the other logic. Single Step and Main Counter Here's the main "single-step through the program" button that triggers whenever the repeater kicks in, plus the main counter that does nothing but go from 1 to 100. Every time the button is pressed, this counter and two other counters (that I'll discuss below) increment by one, and that's all the button does. Two Registers And Some Logic Here are two counters that behave identically except one counts up to three and the other counts up to five. Each counter has an associated delayer and logic gate. In the third little cubbyhole is a dual-action trigger. When the counter gets to the target number, it tells its own delayer "hey, in a sec, try to send a message through my logic gate". It also immedaitely tells the other counter's logic gate "close". Since both logic gates start out open, the first counter to hit its target gets a delayed message through the logic gate. We'll come back to the dual action trigger in a bit. The Output The output is just a "Text Creator", with three messages stored in it: "Fizz", "Buzz", and "Fizz Buzz". However, when it displays a message, it tells both of the logic gates to "open", and it tells the dual-action trigger to reset. How It Actually Works Now, if that were everything, we'd have a system that displays "Fizz" when a number is divisible by three but not five (because the "3' counter sends a delayed message to the text creator, unless the "5" counter told the "3's" logic gate to close), displays "Buzz" when the number is divisible by five but not three (same reason), and displays nothing at all when the number is divisible by both three and five (because both logic gates are shut down before the delayed message can be sent). Further, once you hit the first multiple of 15, nothing would ever be displayed again. The trick is, the logic gates also have a signal for "I got an input, but I'm closed, so it was blocked". Both logic gates send that message to the dual-action trigger. If only one gate is blocked, the other gets through to the text display, and both logic gates and the dual-action trigger get reset (so the trigger forgets that it got a message). But if both logic gates are blocked, then both send a message to the dual-action trigger, which then sends a message to the text display to say "Fizz Buzz". Having displayed some text, the logic gates and the trigger all reset again. What Doesn't Work? Technically, you're supposed to display the messages instead of the number. But I couldn't find a way to display a constantly-changing numeric value as part of a message, only as a counter that shows its value. And I couldn't find a signal for "stop showing your value" or "start showing your value". So, we're breaking the rules and showing the messages in addition to the number. Maybe I'll figure out how to fix that, or maybe they'll update the text creator widget with a formatter that can read values from counters and stuff, but for the moment, please kindly ignore that bit. Category:Blog posts